"""Diagnostic Report Generator.

Provides comprehensive report generation for diagnostic sessions with
multiple output formats and data visualization capabilities.
"""

import json
import logging
import time
from datetime import datetime
from typing import Dict, List, Optional, Any, Union
from dataclasses import dataclass, asdict
from enum import Enum
import base64
from io import BytesIO

from .diagnostic_engine import (
    DiagnosticSession, DiagnosticStatus, DetectedProblem, 
    AnalysisResult, SolutionRecommendation, DiagnosticStep,
    ProblemType, SeverityLevel
)

logger = logging.getLogger(__name__)


class ReportFormat(Enum):
    """Report output format."""
    JSON = "json"
    HTML = "html"
    TEXT = "text"
    MARKDOWN = "markdown"
    PDF = "pdf"
    XML = "xml"


class ReportSection(Enum):
    """Report sections."""
    SUMMARY = "summary"
    PROBLEMS = "problems"
    ANALYSIS = "analysis"
    RECOMMENDATIONS = "recommendations"
    TIMELINE = "timeline"
    STATISTICS = "statistics"
    TECHNICAL_DETAILS = "technical_details"


@dataclass
class ReportTemplate:
    """Report template configuration."""
    template_id: str
    name: str
    description: str
    format: ReportFormat
    sections: List[ReportSection]
    include_charts: bool = False
    include_raw_data: bool = False
    max_problems: int = 100
    max_recommendations: int = 20
    custom_css: Optional[str] = None
    custom_header: Optional[str] = None
    custom_footer: Optional[str] = None


class ReportGenerator:
    """Diagnostic report generator."""
    
    def __init__(self, config: Dict[str, Any]):
        """Initialize report generator.
        
        Args:
            config: Report generator configuration
        """
        self.config = config.get("report_generator", {})
        
        # Report settings
        self.default_format = ReportFormat(self.config.get("default_format", "json"))
        self.include_sensitive_data = self.config.get("include_sensitive_data", False)
        self.compress_reports = self.config.get("compress_reports", False)
        self.max_report_size = self.config.get("max_report_size", 10 * 1024 * 1024)  # 10MB
        
        # Templates
        self.templates: Dict[str, ReportTemplate] = {}
        self._load_default_templates()
        
        # Statistics
        self.statistics = {
            "reports_generated": 0,
            "total_size_bytes": 0,
            "format_usage": {fmt.value: 0 for fmt in ReportFormat}
        }
        
        logger.info(f"ReportGenerator initialized with default format: {self.default_format.value}")
    
    def _load_default_templates(self):
        """Load default report templates."""
        
        # Executive summary template
        self.templates["executive_summary"] = ReportTemplate(
            template_id="executive_summary",
            name="Executive Summary Report",
            description="High-level overview for management",
            format=ReportFormat.HTML,
            sections=[
                ReportSection.SUMMARY,
                ReportSection.PROBLEMS,
                ReportSection.RECOMMENDATIONS,
                ReportSection.STATISTICS
            ],
            include_charts=True,
            include_raw_data=False,
            max_problems=10,
            max_recommendations=5
        )
        
        # Technical detail template
        self.templates["technical_detail"] = ReportTemplate(
            template_id="technical_detail",
            name="Technical Detail Report",
            description="Comprehensive technical analysis",
            format=ReportFormat.JSON,
            sections=[
                ReportSection.SUMMARY,
                ReportSection.PROBLEMS,
                ReportSection.ANALYSIS,
                ReportSection.RECOMMENDATIONS,
                ReportSection.TIMELINE,
                ReportSection.TECHNICAL_DETAILS
            ],
            include_charts=False,
            include_raw_data=True
        )
        
        # Quick summary template
        self.templates["quick_summary"] = ReportTemplate(
            template_id="quick_summary",
            name="Quick Summary Report",
            description="Brief overview of key findings",
            format=ReportFormat.TEXT,
            sections=[
                ReportSection.SUMMARY,
                ReportSection.PROBLEMS,
                ReportSection.RECOMMENDATIONS
            ],
            include_charts=False,
            include_raw_data=False,
            max_problems=5,
            max_recommendations=3
        )
    
    async def generate_report(self, session: DiagnosticSession, 
                            format: Optional[Union[str, ReportFormat]] = None,
                            template_id: Optional[str] = None) -> bytes:
        """Generate diagnostic report for a session.
        
        Args:
            session: Diagnostic session
            format: Output format (overrides template)
            template_id: Template ID to use
            
        Returns:
            Report data as bytes
        """
        start_time = time.time()
        
        try:
            # Determine format
            if format:
                if isinstance(format, str):
                    report_format = ReportFormat(format)
                else:
                    report_format = format
            elif template_id and template_id in self.templates:
                report_format = self.templates[template_id].format
            else:
                report_format = self.default_format
            
            # Get template
            template = self.templates.get(template_id) if template_id else None
            
            # Generate report based on format
            if report_format == ReportFormat.JSON:
                report_data = await self._generate_json_report(session, template)
            elif report_format == ReportFormat.HTML:
                report_data = await self._generate_html_report(session, template)
            elif report_format == ReportFormat.TEXT:
                report_data = await self._generate_text_report(session, template)
            elif report_format == ReportFormat.MARKDOWN:
                report_data = await self._generate_markdown_report(session, template)
            elif report_format == ReportFormat.XML:
                report_data = await self._generate_xml_report(session, template)
            elif report_format == ReportFormat.PDF:
                # PDF generation would require additional libraries
                report_data = await self._generate_pdf_report(session, template)
            else:
                raise ValueError(f"Unsupported report format: {report_format}")
            
            # Check size limit
            if len(report_data) > self.max_report_size:
                logger.warning(f"Report size {len(report_data)} exceeds limit {self.max_report_size}")
                # Truncate or compress as needed
                if self.compress_reports:
                    report_data = self._compress_report(report_data)
            
            # Update statistics
            self.statistics["reports_generated"] += 1
            self.statistics["total_size_bytes"] += len(report_data)
            self.statistics["format_usage"][report_format.value] += 1
            
            generation_time = time.time() - start_time
            logger.info(f"Generated {report_format.value} report in {generation_time:.2f}s, size: {len(report_data)} bytes")
            
            return report_data
            
        except Exception as e:
            logger.error(f"Error generating report: {e}")
            # Return error report
            error_report = {
                "error": str(e),
                "session_id": session.session_id,
                "timestamp": datetime.now().isoformat()
            }
            return json.dumps(error_report, indent=2).encode('utf-8')
    
    async def _generate_json_report(self, session: DiagnosticSession, 
                                   template: Optional[ReportTemplate]) -> bytes:
        """Generate JSON format report."""
        report = {
            "report_metadata": {
                "generated_at": datetime.now().isoformat(),
                "format": "json",
                "version": "1.0",
                "session_id": session.session_id,
                "device_id": session.device_id
            }
        }
        
        sections = template.sections if template else list(ReportSection)
        
        # Add sections based on template or all sections
        if ReportSection.SUMMARY in sections:
            report["summary"] = self._generate_summary_section(session)
        
        if ReportSection.PROBLEMS in sections:
            max_problems = template.max_problems if template else 100
            report["problems"] = self._generate_problems_section(session, max_problems)
        
        if ReportSection.ANALYSIS in sections:
            report["analysis"] = self._generate_analysis_section(session)
        
        if ReportSection.RECOMMENDATIONS in sections:
            max_recs = template.max_recommendations if template else 20
            report["recommendations"] = self._generate_recommendations_section(session, max_recs)
        
        if ReportSection.TIMELINE in sections:
            report["timeline"] = self._generate_timeline_section(session)
        
        if ReportSection.STATISTICS in sections:
            report["statistics"] = self._generate_statistics_section(session)
        
        if ReportSection.TECHNICAL_DETAILS in sections:
            report["technical_details"] = self._generate_technical_details_section(session)
        
        return json.dumps(report, indent=2, default=str).encode('utf-8')
    
    async def _generate_html_report(self, session: DiagnosticSession,
                                   template: Optional[ReportTemplate]) -> bytes:
        """Generate HTML format report."""
        sections = template.sections if template else list(ReportSection)
        
        html_parts = []
        
        # HTML header
        html_parts.append("""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Diagnostic Report - {session_id}</title>
    <style>
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #f5f5f5;
        }}
        .header {{
            background: #2c3e50;
            color: white;
            padding: 20px;
            border-radius: 8px 8px 0 0;
            margin-bottom: 0;
        }}
        .content {{
            background: white;
            padding: 30px;
            border-radius: 0 0 8px 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }}
        h1 {{ margin: 0; font-size: 28px; }}
        h2 {{ 
            color: #2c3e50;
            border-bottom: 2px solid #ecf0f1;
            padding-bottom: 10px;
            margin-top: 30px;
        }}
        .summary-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin: 20px 0;
        }}
        .summary-card {{
            background: #f8f9fa;
            padding: 15px;
            border-radius: 6px;
            border-left: 4px solid #3498db;
        }}
        .problem {{
            background: #fff5f5;
            border-left: 4px solid #e74c3c;
            padding: 15px;
            margin: 15px 0;
            border-radius: 4px;
        }}
        .problem.critical {{ border-left-color: #c0392b; background: #ffe5e5; }}
        .problem.high {{ border-left-color: #e74c3c; }}
        .problem.medium {{ border-left-color: #f39c12; background: #fffaf0; }}
        .problem.low {{ border-left-color: #95a5a6; background: #f9f9f9; }}
        .recommendation {{
            background: #f0f9ff;
            border-left: 4px solid #2ecc71;
            padding: 15px;
            margin: 15px 0;
            border-radius: 4px;
        }}
        .badge {{
            display: inline-block;
            padding: 3px 8px;
            border-radius: 3px;
            font-size: 12px;
            font-weight: bold;
            margin-right: 5px;
        }}
        .badge.critical {{ background: #c0392b; color: white; }}
        .badge.high {{ background: #e74c3c; color: white; }}
        .badge.medium {{ background: #f39c12; color: white; }}
        .badge.low {{ background: #95a5a6; color: white; }}
        .badge.info {{ background: #3498db; color: white; }}
        .timeline {{
            position: relative;
            padding-left: 30px;
        }}
        .timeline-item {{
            position: relative;
            padding: 10px 0;
            border-left: 2px solid #ecf0f1;
            padding-left: 20px;
            margin-left: 10px;
        }}
        .timeline-item::before {{
            content: '';
            position: absolute;
            left: -7px;
            top: 15px;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: #3498db;
            border: 2px solid white;
        }}
        .stats-table {{
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }}
        .stats-table th, .stats-table td {{
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #ecf0f1;
        }}
        .stats-table th {{
            background: #f8f9fa;
            font-weight: 600;
        }}
        .footer {{
            margin-top: 40px;
            padding-top: 20px;
            border-top: 1px solid #ecf0f1;
            text-align: center;
            color: #7f8c8d;
            font-size: 14px;
        }}
        {custom_css}
    </style>
</head>
<body>""".format(
            session_id=session.session_id,
            custom_css=template.custom_css if template and template.custom_css else ""
        ))
        
        # Header
        if template and template.custom_header:
            html_parts.append(template.custom_header)
        else:
            html_parts.append(f"""
    <div class="header">
        <h1>Diagnostic Report</h1>
        <p>Session ID: {session.session_id}</p>
        <p>Device ID: {session.device_id}</p>
        <p>Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
    </div>""")
        
        html_parts.append('<div class="content">')
        
        # Generate sections
        if ReportSection.SUMMARY in sections:
            html_parts.append(self._generate_html_summary(session))
        
        if ReportSection.PROBLEMS in sections:
            max_problems = template.max_problems if template else 100
            html_parts.append(self._generate_html_problems(session, max_problems))
        
        if ReportSection.ANALYSIS in sections:
            html_parts.append(self._generate_html_analysis(session))
        
        if ReportSection.RECOMMENDATIONS in sections:
            max_recs = template.max_recommendations if template else 20
            html_parts.append(self._generate_html_recommendations(session, max_recs))
        
        if ReportSection.TIMELINE in sections:
            html_parts.append(self._generate_html_timeline(session))
        
        if ReportSection.STATISTICS in sections:
            html_parts.append(self._generate_html_statistics(session))
        
        html_parts.append('</div>')
        
        # Footer
        if template and template.custom_footer:
            html_parts.append(template.custom_footer)
        else:
            html_parts.append("""
    <div class="footer">
        <p>This report was automatically generated by the Diagnostic System</p>
        <p>&copy; 2025 Cloud Printer Base System</p>
    </div>""")
        
        html_parts.append("""
</body>
</html>""")
        
        return ''.join(html_parts).encode('utf-8')
    
    async def _generate_text_report(self, session: DiagnosticSession,
                                   template: Optional[ReportTemplate]) -> bytes:
        """Generate plain text format report."""
        lines = []
        sections = template.sections if template else list(ReportSection)
        
        # Header
        lines.append("=" * 80)
        lines.append("DIAGNOSTIC REPORT")
        lines.append("=" * 80)
        lines.append(f"Session ID: {session.session_id}")
        lines.append(f"Device ID: {session.device_id}")
        lines.append(f"Status: {session.status.value}")
        lines.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        lines.append("")
        
        # Sections
        if ReportSection.SUMMARY in sections:
            lines.append("-" * 80)
            lines.append("SUMMARY")
            lines.append("-" * 80)
            summary = self._generate_summary_section(session)
            lines.append(f"Problem Description: {summary['problem_description']}")
            lines.append(f"Total Problems Detected: {summary['total_problems']}")
            lines.append(f"Total Recommendations: {summary['total_recommendations']}")
            lines.append(f"Overall Confidence: {summary['overall_confidence']:.1%}")
            lines.append(f"Duration: {summary['duration_seconds']}s")
            lines.append("")
        
        if ReportSection.PROBLEMS in sections:
            lines.append("-" * 80)
            lines.append("DETECTED PROBLEMS")
            lines.append("-" * 80)
            max_problems = template.max_problems if template else 100
            problems = self._generate_problems_section(session, max_problems)
            for i, problem in enumerate(problems, 1):
                lines.append(f"\n{i}. {problem['title']}")
                lines.append(f"   Type: {problem['type']}")
                lines.append(f"   Severity: {problem['severity']}")
                lines.append(f"   Confidence: {problem['confidence']:.1%}")
                lines.append(f"   Description: {problem['description']}")
                if problem['affected_components']:
                    lines.append(f"   Affected Components: {', '.join(problem['affected_components'])}")
            lines.append("")
        
        if ReportSection.RECOMMENDATIONS in sections:
            lines.append("-" * 80)
            lines.append("RECOMMENDATIONS")
            lines.append("-" * 80)
            max_recs = template.max_recommendations if template else 20
            recommendations = self._generate_recommendations_section(session, max_recs)
            for i, rec in enumerate(recommendations, 1):
                lines.append(f"\n{i}. {rec['title']}")
                lines.append(f"   Type: {rec['type']}")
                lines.append(f"   Confidence: {rec['confidence']:.1%}")
                lines.append(f"   Estimated Time: {rec['estimated_time']}s")
                lines.append(f"   Automated: {'Yes' if rec['is_automated'] else 'No'}")
                lines.append(f"   Risk Level: {rec['risk_level']}")
                lines.append(f"   Description: {rec['description']}")
                if rec.get('manual_steps'):
                    lines.append("   Manual Steps:")
                    for step in rec['manual_steps']:
                        lines.append(f"     - {step}")
            lines.append("")
        
        if ReportSection.STATISTICS in sections:
            lines.append("-" * 80)
            lines.append("STATISTICS")
            lines.append("-" * 80)
            stats = self._generate_statistics_section(session)
            lines.append(f"Session Duration: {stats['session_duration']}s")
            lines.append(f"Problems by Severity:")
            for severity, count in stats['problems_by_severity'].items():
                lines.append(f"  - {severity}: {count}")
            lines.append(f"Problems by Type:")
            for prob_type, count in stats['problems_by_type'].items():
                lines.append(f"  - {prob_type}: {count}")
            lines.append(f"Average Problem Confidence: {stats['average_problem_confidence']:.1%}")
            lines.append(f"Average Recommendation Confidence: {stats['average_recommendation_confidence']:.1%}")
            lines.append("")
        
        # Footer
        lines.append("=" * 80)
        lines.append("END OF REPORT")
        lines.append("=" * 80)
        
        return '\n'.join(lines).encode('utf-8')
    
    async def _generate_markdown_report(self, session: DiagnosticSession,
                                       template: Optional[ReportTemplate]) -> bytes:
        """Generate Markdown format report."""
        lines = []
        sections = template.sections if template else list(ReportSection)
        
        # Header
        lines.append("# Diagnostic Report")
        lines.append("")
        lines.append(f"**Session ID:** `{session.session_id}`  ")
        lines.append(f"**Device ID:** `{session.device_id}`  ")
        lines.append(f"**Status:** {session.status.value}  ")
        lines.append(f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}  ")
        lines.append("")
        
        # Table of Contents
        lines.append("## Table of Contents")
        lines.append("")
        toc_items = []
        if ReportSection.SUMMARY in sections:
            toc_items.append("- [Summary](#summary)")
        if ReportSection.PROBLEMS in sections:
            toc_items.append("- [Detected Problems](#detected-problems)")
        if ReportSection.ANALYSIS in sections:
            toc_items.append("- [Analysis Results](#analysis-results)")
        if ReportSection.RECOMMENDATIONS in sections:
            toc_items.append("- [Recommendations](#recommendations)")
        if ReportSection.TIMELINE in sections:
            toc_items.append("- [Timeline](#timeline)")
        if ReportSection.STATISTICS in sections:
            toc_items.append("- [Statistics](#statistics)")
        lines.extend(toc_items)
        lines.append("")
        
        # Sections
        if ReportSection.SUMMARY in sections:
            lines.append("## Summary")
            lines.append("")
            summary = self._generate_summary_section(session)
            lines.append(f"**Problem Description:** {summary['problem_description']}")
            lines.append("")
            lines.append("| Metric | Value |")
            lines.append("|--------|-------|")
            lines.append(f"| Total Problems | {summary['total_problems']} |")
            lines.append(f"| Total Recommendations | {summary['total_recommendations']} |")
            lines.append(f"| Overall Confidence | {summary['overall_confidence']:.1%} |")
            lines.append(f"| Session Duration | {summary['duration_seconds']}s |")
            lines.append("")
        
        if ReportSection.PROBLEMS in sections:
            lines.append("## Detected Problems")
            lines.append("")
            max_problems = template.max_problems if template else 100
            problems = self._generate_problems_section(session, max_problems)
            
            for i, problem in enumerate(problems, 1):
                severity_emoji = {
                    "critical": "🔴",
                    "high": "🟠",
                    "medium": "🟡",
                    "low": "🟢",
                    "info": "🔵"
                }.get(problem['severity'], "⚪")
                
                lines.append(f"### {i}. {severity_emoji} {problem['title']}")
                lines.append("")
                lines.append(f"- **Type:** `{problem['type']}`")
                lines.append(f"- **Severity:** `{problem['severity']}`")
                lines.append(f"- **Confidence:** {problem['confidence']:.1%}")
                lines.append(f"- **Description:** {problem['description']}")
                if problem['affected_components']:
                    lines.append(f"- **Affected Components:** {', '.join(f'`{c}`' for c in problem['affected_components'])}")
                lines.append("")
        
        if ReportSection.RECOMMENDATIONS in sections:
            lines.append("## Recommendations")
            lines.append("")
            max_recs = template.max_recommendations if template else 20
            recommendations = self._generate_recommendations_section(session, max_recs)
            
            for i, rec in enumerate(recommendations, 1):
                automation_badge = "🤖" if rec['is_automated'] else "👤"
                lines.append(f"### {i}. {automation_badge} {rec['title']}")
                lines.append("")
                lines.append(f"- **Type:** `{rec['type']}`")
                lines.append(f"- **Confidence:** {rec['confidence']:.1%}")
                lines.append(f"- **Estimated Time:** {rec['estimated_time']}s")
                lines.append(f"- **Risk Level:** `{rec['risk_level']}`")
                lines.append(f"- **Description:** {rec['description']}")
                
                if rec.get('manual_steps'):
                    lines.append("")
                    lines.append("**Manual Steps:**")
                    for j, step in enumerate(rec['manual_steps'], 1):
                        lines.append(f"{j}. {step}")
                lines.append("")
        
        if ReportSection.STATISTICS in sections:
            lines.append("## Statistics")
            lines.append("")
            stats = self._generate_statistics_section(session)
            
            lines.append("### Session Metrics")
            lines.append("")
            lines.append("| Metric | Value |")
            lines.append("|--------|-------|")
            lines.append(f"| Session Duration | {stats['session_duration']}s |")
            lines.append(f"| Completion Rate | {stats['completion_rate']:.1%} |")
            lines.append(f"| Average Problem Confidence | {stats['average_problem_confidence']:.1%} |")
            lines.append(f"| Average Recommendation Confidence | {stats['average_recommendation_confidence']:.1%} |")
            lines.append("")
            
            lines.append("### Problem Distribution")
            lines.append("")
            lines.append("#### By Severity")
            for severity, count in stats['problems_by_severity'].items():
                lines.append(f"- **{severity}:** {count}")
            lines.append("")
            lines.append("#### By Type")
            for prob_type, count in stats['problems_by_type'].items():
                lines.append(f"- **{prob_type}:** {count}")
            lines.append("")
        
        lines.append("---")
        lines.append("*This report was automatically generated by the Diagnostic System*")
        
        return '\n'.join(lines).encode('utf-8')
    
    async def _generate_xml_report(self, session: DiagnosticSession,
                                  template: Optional[ReportTemplate]) -> bytes:
        """Generate XML format report."""
        from xml.etree.ElementTree import Element, SubElement, tostring
        from xml.dom import minidom
        
        # Root element
        root = Element('DiagnosticReport')
        root.set('version', '1.0')
        root.set('generated', datetime.now().isoformat())
        
        # Metadata
        metadata = SubElement(root, 'Metadata')
        SubElement(metadata, 'SessionId').text = session.session_id
        SubElement(metadata, 'DeviceId').text = session.device_id
        SubElement(metadata, 'Status').text = session.status.value
        SubElement(metadata, 'CreatedAt').text = session.created_at.isoformat()
        if session.completed_at:
            SubElement(metadata, 'CompletedAt').text = session.completed_at.isoformat()
        
        sections = template.sections if template else list(ReportSection)
        
        # Summary section
        if ReportSection.SUMMARY in sections:
            summary_data = self._generate_summary_section(session)
            summary = SubElement(root, 'Summary')
            SubElement(summary, 'ProblemDescription').text = summary_data['problem_description']
            SubElement(summary, 'TotalProblems').text = str(summary_data['total_problems'])
            SubElement(summary, 'TotalRecommendations').text = str(summary_data['total_recommendations'])
            SubElement(summary, 'OverallConfidence').text = str(summary_data['overall_confidence'])
            SubElement(summary, 'Duration').text = str(summary_data['duration_seconds'])
        
        # Problems section
        if ReportSection.PROBLEMS in sections:
            max_problems = template.max_problems if template else 100
            problems_data = self._generate_problems_section(session, max_problems)
            problems = SubElement(root, 'Problems')
            
            for problem_data in problems_data:
                problem = SubElement(problems, 'Problem')
                problem.set('id', problem_data['id'])
                SubElement(problem, 'Title').text = problem_data['title']
                SubElement(problem, 'Type').text = problem_data['type']
                SubElement(problem, 'Severity').text = problem_data['severity']
                SubElement(problem, 'Description').text = problem_data['description']
                SubElement(problem, 'Confidence').text = str(problem_data['confidence'])
                
                if problem_data['affected_components']:
                    components = SubElement(problem, 'AffectedComponents')
                    for comp in problem_data['affected_components']:
                        SubElement(components, 'Component').text = comp
        
        # Recommendations section
        if ReportSection.RECOMMENDATIONS in sections:
            max_recs = template.max_recommendations if template else 20
            recs_data = self._generate_recommendations_section(session, max_recs)
            recommendations = SubElement(root, 'Recommendations')
            
            for rec_data in recs_data:
                rec = SubElement(recommendations, 'Recommendation')
                rec.set('id', rec_data['id'])
                SubElement(rec, 'Title').text = rec_data['title']
                SubElement(rec, 'Type').text = rec_data['type']
                SubElement(rec, 'Description').text = rec_data['description']
                SubElement(rec, 'Confidence').text = str(rec_data['confidence'])
                SubElement(rec, 'EstimatedTime').text = str(rec_data['estimated_time'])
                SubElement(rec, 'IsAutomated').text = str(rec_data['is_automated'])
                SubElement(rec, 'RiskLevel').text = rec_data['risk_level']
                
                if rec_data.get('manual_steps'):
                    steps = SubElement(rec, 'ManualSteps')
                    for step_text in rec_data['manual_steps']:
                        SubElement(steps, 'Step').text = step_text
        
        # Convert to pretty XML
        rough_string = tostring(root, encoding='unicode')
        reparsed = minidom.parseString(rough_string)
        pretty_xml = reparsed.toprettyxml(indent="  ", encoding='utf-8')
        
        return pretty_xml
    
    async def _generate_pdf_report(self, session: DiagnosticSession,
                                  template: Optional[ReportTemplate]) -> bytes:
        """Generate PDF format report (placeholder - requires additional libraries)."""
        # In a real implementation, this would use libraries like:
        # - reportlab for PDF generation
        # - weasyprint for HTML to PDF conversion
        # - matplotlib for charts
        
        # For now, return a placeholder message
        placeholder = {
            "message": "PDF generation requires additional libraries",
            "session_id": session.session_id,
            "alternative": "Please use HTML or other formats"
        }
        return json.dumps(placeholder).encode('utf-8')
    
    def _generate_summary_section(self, session: DiagnosticSession) -> Dict[str, Any]:
        """Generate summary section data."""
        duration = 0
        if session.started_at and session.completed_at:
            duration = int((session.completed_at - session.started_at).total_seconds())
        elif session.started_at:
            duration = int((datetime.now() - session.started_at).total_seconds())
        
        return {
            "session_id": session.session_id,
            "device_id": session.device_id,
            "status": session.status.value,
            "problem_description": session.problem_description,
            "total_problems": len(session.detected_problems),
            "total_recommendations": len(session.recommendations),
            "overall_confidence": session.confidence_score,
            "completion_rate": session.completion_rate,
            "duration_seconds": duration,
            "auto_fix_count": session.auto_fix_count,
            "manual_step_count": session.manual_step_count
        }
    
    def _generate_problems_section(self, session: DiagnosticSession, 
                                  max_problems: int) -> List[Dict[str, Any]]:
        """Generate problems section data."""
        problems = []
        for problem in session.detected_problems[:max_problems]:
            problems.append({
                "id": problem.problem_id,
                "type": problem.problem_type.value,
                "severity": problem.severity.value,
                "title": problem.title,
                "description": problem.description,
                "detector": problem.detector_name,
                "detected_at": problem.detected_at.isoformat(),
                "confidence": problem.confidence,
                "affected_components": problem.affected_components,
                "error_codes": problem.error_codes,
                "is_resolved": problem.is_resolved,
                "resolution_method": problem.resolution_method
            })
        return problems
    
    def _generate_analysis_section(self, session: DiagnosticSession) -> List[Dict[str, Any]]:
        """Generate analysis section data."""
        analyses = []
        for analysis in session.analysis_results:
            analyses.append({
                "id": analysis.analysis_id,
                "type": analysis.analysis_type,
                "root_cause": analysis.root_cause,
                "contributing_factors": analysis.contributing_factors,
                "correlation_score": analysis.correlation_score,
                "pattern_matches": analysis.pattern_matches,
                "conclusion": analysis.conclusion,
                "confidence": analysis.confidence
            })
        return analyses
    
    def _generate_recommendations_section(self, session: DiagnosticSession,
                                        max_recommendations: int) -> List[Dict[str, Any]]:
        """Generate recommendations section data."""
        recommendations = []
        for rec in session.recommendations[:max_recommendations]:
            recommendations.append({
                "id": rec.recommendation_id,
                "type": rec.solution_type,
                "title": rec.title,
                "description": rec.description,
                "confidence": rec.confidence,
                "success_rate": rec.success_rate,
                "estimated_time": rec.estimated_time,
                "difficulty": rec.difficulty,
                "is_automated": rec.is_automated,
                "requires_approval": rec.requires_approval,
                "risk_level": rec.risk_level,
                "rollback_available": rec.rollback_available,
                "manual_steps": rec.manual_steps,
                "kb_articles": rec.related_kb_articles
            })
        return recommendations
    
    def _generate_timeline_section(self, session: DiagnosticSession) -> List[Dict[str, Any]]:
        """Generate timeline section data."""
        timeline = []
        
        # Add session events
        timeline.append({
            "timestamp": session.created_at.isoformat(),
            "event": "Session Created",
            "description": f"Diagnostic session initiated for {session.problem_description}"
        })
        
        if session.started_at:
            timeline.append({
                "timestamp": session.started_at.isoformat(),
                "event": "Session Started",
                "description": "Diagnostic process began"
            })
        
        # Add diagnostic steps
        for step in session.diagnostic_steps:
            timeline.append({
                "timestamp": step.started_at.isoformat() if step.started_at else "",
                "event": f"Step: {step.description}",
                "status": step.status,
                "duration": int((step.completed_at - step.started_at).total_seconds()) if step.completed_at and step.started_at else 0
            })
        
        # Add problem detections
        for problem in session.detected_problems:
            timeline.append({
                "timestamp": problem.detected_at.isoformat(),
                "event": f"Problem Detected: {problem.title}",
                "severity": problem.severity.value,
                "type": problem.problem_type.value
            })
        
        if session.completed_at:
            timeline.append({
                "timestamp": session.completed_at.isoformat(),
                "event": "Session Completed",
                "description": f"Diagnostic completed with status: {session.status.value}"
            })
        
        # Sort by timestamp
        timeline.sort(key=lambda x: x.get('timestamp', ''))
        
        return timeline
    
    def _generate_statistics_section(self, session: DiagnosticSession) -> Dict[str, Any]:
        """Generate statistics section data."""
        # Calculate problem statistics
        problems_by_severity = {}
        problems_by_type = {}
        total_confidence = 0.0
        
        for problem in session.detected_problems:
            # By severity
            severity = problem.severity.value
            problems_by_severity[severity] = problems_by_severity.get(severity, 0) + 1
            
            # By type
            prob_type = problem.problem_type.value
            problems_by_type[prob_type] = problems_by_type.get(prob_type, 0) + 1
            
            # Confidence
            total_confidence += problem.confidence
        
        avg_problem_confidence = total_confidence / len(session.detected_problems) if session.detected_problems else 0
        
        # Calculate recommendation statistics
        rec_confidence = sum(r.confidence for r in session.recommendations)
        avg_rec_confidence = rec_confidence / len(session.recommendations) if session.recommendations else 0
        
        # Session duration
        duration = 0
        if session.started_at and session.completed_at:
            duration = int((session.completed_at - session.started_at).total_seconds())
        
        return {
            "session_duration": duration,
            "completion_rate": session.completion_rate,
            "problems_detected": len(session.detected_problems),
            "problems_by_severity": problems_by_severity,
            "problems_by_type": problems_by_type,
            "average_problem_confidence": avg_problem_confidence,
            "recommendations_generated": len(session.recommendations),
            "average_recommendation_confidence": avg_rec_confidence,
            "auto_fix_available": session.auto_fix_count,
            "manual_steps_required": session.manual_step_count
        }
    
    def _generate_technical_details_section(self, session: DiagnosticSession) -> Dict[str, Any]:
        """Generate technical details section."""
        return {
            "session_id": session.session_id,
            "device_id": session.device_id,
            "user_id": session.user_id,
            "priority": session.priority,
            "tags": session.tags,
            "estimated_duration": session.estimated_duration,
            "actual_duration": session.actual_duration,
            "diagnostic_steps": [
                {
                    "step_id": step.step_id,
                    "type": step.step_type,
                    "description": step.description,
                    "status": step.status,
                    "started_at": step.started_at.isoformat() if step.started_at else None,
                    "completed_at": step.completed_at.isoformat() if step.completed_at else None,
                    "result_data": step.result_data,
                    "error_message": step.error_message
                }
                for step in session.diagnostic_steps
            ],
            "raw_problem_data": [
                {
                    "problem_id": p.problem_id,
                    "symptom_data": p.symptom_data,
                    "historical_occurrences": p.historical_occurrences
                }
                for p in session.detected_problems
            ] if self.include_sensitive_data else []
        }
    
    def _generate_html_summary(self, session: DiagnosticSession) -> str:
        """Generate HTML summary section."""
        summary = self._generate_summary_section(session)
        
        return f"""
        <h2>Summary</h2>
        <p><strong>Problem Description:</strong> {summary['problem_description']}</p>
        
        <div class="summary-grid">
            <div class="summary-card">
                <h3>{summary['total_problems']}</h3>
                <p>Problems Detected</p>
            </div>
            <div class="summary-card">
                <h3>{summary['total_recommendations']}</h3>
                <p>Recommendations</p>
            </div>
            <div class="summary-card">
                <h3>{summary['overall_confidence']:.1%}</h3>
                <p>Overall Confidence</p>
            </div>
            <div class="summary-card">
                <h3>{summary['duration_seconds']}s</h3>
                <p>Duration</p>
            </div>
        </div>
        """
    
    def _generate_html_problems(self, session: DiagnosticSession, max_problems: int) -> str:
        """Generate HTML problems section."""
        html = ["<h2>Detected Problems</h2>"]
        
        problems = self._generate_problems_section(session, max_problems)
        for problem in problems:
            severity_class = problem['severity']
            html.append(f"""
            <div class="problem {severity_class}">
                <h3>{problem['title']} <span class="badge {severity_class}">{problem['severity'].upper()}</span></h3>
                <p>{problem['description']}</p>
                <p><strong>Type:</strong> {problem['type']} | 
                   <strong>Confidence:</strong> {problem['confidence']:.1%} |
                   <strong>Detector:</strong> {problem['detector']}</p>
                {f"<p><strong>Affected Components:</strong> {', '.join(problem['affected_components'])}</p>" if problem['affected_components'] else ""}
            </div>
            """)
        
        return ''.join(html)
    
    def _generate_html_analysis(self, session: DiagnosticSession) -> str:
        """Generate HTML analysis section."""
        html = ["<h2>Analysis Results</h2>"]
        
        analyses = self._generate_analysis_section(session)
        for analysis in analyses:
            html.append(f"""
            <div class="analysis">
                <h3>{analysis['type'].replace('_', ' ').title()}</h3>
                <p>{analysis['conclusion']}</p>
                {f"<p><strong>Root Cause:</strong> {analysis['root_cause']}</p>" if analysis['root_cause'] else ""}
                <p><strong>Confidence:</strong> {analysis['confidence']:.1%} | 
                   <strong>Correlation Score:</strong> {analysis['correlation_score']:.2f}</p>
            </div>
            """)
        
        return ''.join(html)
    
    def _generate_html_recommendations(self, session: DiagnosticSession, max_recs: int) -> str:
        """Generate HTML recommendations section."""
        html = ["<h2>Recommendations</h2>"]
        
        recommendations = self._generate_recommendations_section(session, max_recs)
        for rec in recommendations:
            auto_badge = '<span class="badge info">AUTOMATED</span>' if rec['is_automated'] else ''
            html.append(f"""
            <div class="recommendation">
                <h3>{rec['title']} {auto_badge}</h3>
                <p>{rec['description']}</p>
                <p><strong>Confidence:</strong> {rec['confidence']:.1%} | 
                   <strong>Success Rate:</strong> {rec['success_rate']:.1%} |
                   <strong>Est. Time:</strong> {rec['estimated_time']}s |
                   <strong>Risk:</strong> {rec['risk_level']}</p>
                {self._format_manual_steps_html(rec['manual_steps']) if rec.get('manual_steps') else ""}
            </div>
            """)
        
        return ''.join(html)
    
    def _format_manual_steps_html(self, steps: List[str]) -> str:
        """Format manual steps as HTML."""
        if not steps:
            return ""
        
        html = ["<p><strong>Manual Steps:</strong></p><ol>"]
        for step in steps:
            html.append(f"<li>{step}</li>")
        html.append("</ol>")
        
        return ''.join(html)
    
    def _generate_html_timeline(self, session: DiagnosticSession) -> str:
        """Generate HTML timeline section."""
        html = ["<h2>Timeline</h2>", '<div class="timeline">']
        
        timeline = self._generate_timeline_section(session)
        for event in timeline:
            html.append(f"""
            <div class="timeline-item">
                <strong>{event['event']}</strong><br>
                <small>{event.get('timestamp', 'N/A')}</small>
                {f"<br>{event.get('description', '')}" if event.get('description') else ""}
            </div>
            """)
        
        html.append("</div>")
        return ''.join(html)
    
    def _generate_html_statistics(self, session: DiagnosticSession) -> str:
        """Generate HTML statistics section."""
        stats = self._generate_statistics_section(session)
        
        html = ["<h2>Statistics</h2>"]
        
        # Session statistics table
        html.append("""
        <table class="stats-table">
            <thead>
                <tr>
                    <th>Metric</th>
                    <th>Value</th>
                </tr>
            </thead>
            <tbody>
        """)
        
        html.append(f"""
            <tr><td>Session Duration</td><td>{stats['session_duration']}s</td></tr>
            <tr><td>Completion Rate</td><td>{stats['completion_rate']:.1%}</td></tr>
            <tr><td>Problems Detected</td><td>{stats['problems_detected']}</td></tr>
            <tr><td>Recommendations Generated</td><td>{stats['recommendations_generated']}</td></tr>
            <tr><td>Average Problem Confidence</td><td>{stats['average_problem_confidence']:.1%}</td></tr>
            <tr><td>Average Recommendation Confidence</td><td>{stats['average_recommendation_confidence']:.1%}</td></tr>
        """)
        
        html.append("</tbody></table>")
        
        # Problem distribution
        html.append("<h3>Problem Distribution</h3>")
        html.append('<div class="summary-grid">')
        
        # By severity
        html.append('<div class="summary-card"><h4>By Severity</h4>')
        for severity, count in stats['problems_by_severity'].items():
            html.append(f"<p>{severity}: {count}</p>")
        html.append('</div>')
        
        # By type
        html.append('<div class="summary-card"><h4>By Type</h4>')
        for prob_type, count in stats['problems_by_type'].items():
            html.append(f"<p>{prob_type}: {count}</p>")
        html.append('</div>')
        
        html.append('</div>')
        
        return ''.join(html)
    
    def _compress_report(self, data: bytes) -> bytes:
        """Compress report data."""
        import gzip
        return gzip.compress(data)
    
    def get_statistics(self) -> Dict[str, Any]:
        """Get report generator statistics."""
        return {
            "generator_statistics": self.statistics.copy(),
            "templates": {
                template_id: {
                    "name": template.name,
                    "format": template.format.value,
                    "sections": [s.value for s in template.sections]
                }
                for template_id, template in self.templates.items()
            },
            "configuration": {
                "default_format": self.default_format.value,
                "compress_reports": self.compress_reports,
                "max_report_size": self.max_report_size
            }
        }


# Example usage and testing
if __name__ == "__main__":
    import asyncio
    from .diagnostic_engine import DiagnosticSession, DiagnosticStatus
    
    async def test_report_generator():
        """Test report generator."""
        # Create configuration
        config = {
            "report_generator": {
                "default_format": "html",
                "compress_reports": False
            }
        }
        
        # Create report generator
        generator = ReportGenerator(config)
        
        # Create a mock session for testing
        session = DiagnosticSession(
            session_id="test_session_001",
            device_id="test_device",
            user_id="test_user",
            problem_description="System performance issues",
            status=DiagnosticStatus.COMPLETED,
            created_at=datetime.now(),
            started_at=datetime.now(),
            completed_at=datetime.now()
        )
        
        # Add some mock problems
        from .diagnostic_engine import DetectedProblem, ProblemType, SeverityLevel
        session.detected_problems = [
            DetectedProblem(
                problem_id="prob_001",
                problem_type=ProblemType.NETWORK_CONNECTIVITY,
                severity=SeverityLevel.HIGH,
                title="Network connection failure",
                description="Cannot connect to external services",
                detector_name="network_detector",
                detected_at=datetime.now(),
                confidence=0.9,
                symptom_data={"error": "timeout"},
                affected_components=["network_interface", "dns"]
            )
        ]
        
        # Add mock recommendations
        from .diagnostic_engine import SolutionRecommendation
        session.recommendations = [
            SolutionRecommendation(
                recommendation_id="rec_001",
                solution_type="service_restart",
                title="Restart network service",
                description="Restart network services to restore connectivity",
                confidence=0.85,
                success_rate=0.9,
                estimated_time=60,
                difficulty="easy",
                is_automated=True,
                requires_approval=False,
                risk_level="low"
            )
        ]
        
        session.confidence_score = 0.85
        session.completion_rate = 1.0
        
        print("Testing report generation...")
        
        # Test different formats
        for format_type in [ReportFormat.JSON, ReportFormat.HTML, ReportFormat.TEXT, ReportFormat.MARKDOWN]:
            print(f"\nGenerating {format_type.value} report...")
            report = await generator.generate_report(session, format=format_type)
            print(f"Report size: {len(report)} bytes")
            
            # Save sample report
            filename = f"test_report.{format_type.value}"
            with open(filename, 'wb') as f:
                f.write(report)
            print(f"Saved to {filename}")
        
        # Get statistics
        stats = generator.get_statistics()
        print(f"\nGenerator statistics: {stats}")
    
    # Run test
    asyncio.run(test_report_generator())